package element.synt;

import element.base.Synt;
import element.base.TreeNode;
import element.base.Word;
import element.base.Wordtype;
import intermediate_representation.*;
import table.InterCodeTable;

import java.util.ArrayList;

// Stmt → LVal '=' Exp ';'
// | [Exp] ';'
// | Block
// | 'if' '(' Cond ')' Stmt [ 'else' Stmt ]
// | 'while' '(' Cond ')' Stmt
// | 'break' ';' | 'continue' ';'
// | 'return' [Exp] ';'
// | LVal '=' 'getint''('')'';'
// | 'printf''('FormatString{','Exp}')'';'
public class Stmt extends Synt {
    @Override
    public void tointerRP() {
        int nowindex = InterCodeTable.regindex;
        ArrayList<TreeNode> nodes = this.getNodes();
        TreeNode node0 = nodes.get(0);
        if (node0 instanceof LVal) {
            String name = ((LVal) node0).toFormat();
            if (nodes.get(2) instanceof Exp) {
                Exp cal = (Exp) nodes.get(2);
                cal.tointerRP();
                String nowvar = InterCodeTable.nowVar;
                if (nowvar.charAt(0) == '$' && !name.contains("[")) {
                    InterCodeTable.setLastName(name);
                } else {
                    AssignRP assignRP = new AssignRP(name, nowvar);
                    InterCodeTable.addCode(assignRP);
                }
            } else {
                if (name.contains("[")) {
                    InterCodeTable.pushvar();
                    GetintRP getintRP = new GetintRP(InterCodeTable.nowVar);
                    InterCodeTable.addCode(getintRP);
                    AssignRP assignRP = new AssignRP(name, InterCodeTable.nowVar);
                    InterCodeTable.addCode(assignRP);
                } else {
                    GetintRP getintRP = new GetintRP(name);
                    InterCodeTable.addCode(getintRP);
                }
            }
        } else if (node0 instanceof Exp) {
            ((Exp) node0).tofuncRP();
        } else if (node0 instanceof Block) {
            ((Block) node0).tointerRP();
        } else if (node0.isWord(Wordtype.PRINTFTK)) {
            String formatstring = ((Word) nodes.get(2)).getContent();
            PrintRP printRP = new PrintRP(formatstring);
            for (TreeNode node: nodes) {
                if (node instanceof Exp) {
                    ((Exp) node).tointerRP();
                    String para = InterCodeTable.nowVar;
                    printRP.addPara(para);
                }
            }
            InterCodeTable.addCode(printRP);
        } else if (node0.isWord(Wordtype.RETURNTK)) {
            if (nodes.size() == 3) {
                Exp exp = (Exp) nodes.get(1);
                exp.tointerRP();
                ReturnRP returnRP = new ReturnRP(InterCodeTable.nowVar);
                InterCodeTable.addCode(returnRP);
            } else {
                ReturnRP returnRP = new ReturnRP();
                InterCodeTable.addCode(returnRP);
            }
        } else if (node0.isWord(Wordtype.IFTK)) {
            Cond cond = (Cond) nodes.get(2);
            String ifBeginLabel = InterCodeTable.pushLabel();
            String ifEndLabel = InterCodeTable.pushLabel();
            if (nodes.size() == 7) {
                String elseLabel = InterCodeTable.pushLabel();
                cond.Jump(ifBeginLabel, elseLabel);
                LabelRP labelRP = new LabelRP(ifBeginLabel);
                InterCodeTable.addCode(labelRP);
                Stmt ifstmt = (Stmt) nodes.get(4);
                ifstmt.tointerRP();
                JumpRP jumpRP = new JumpRP(ifEndLabel);
                InterCodeTable.addCode(jumpRP);
                LabelRP labelRP1 = new LabelRP(elseLabel);
                InterCodeTable.addCode(labelRP1);
                Stmt elsestmt = (Stmt) nodes.get(6);
                elsestmt.tointerRP();
                LabelRP labelRP2 = new LabelRP(ifEndLabel);
                InterCodeTable.addCode(labelRP2);
            } else {
                cond.Jump(ifBeginLabel, ifEndLabel);
                LabelRP labelRP = new LabelRP(ifBeginLabel);
                InterCodeTable.addCode(labelRP);
                Stmt ifstmt = (Stmt) nodes.get(4);
                ifstmt.tointerRP();
                LabelRP labelRP1 = new LabelRP(ifEndLabel);
                InterCodeTable.addCode(labelRP1);
            }
        } else if (node0.isWord(Wordtype.WHILETK)) {
            String formerWhileBegin = InterCodeTable.nowWhileBeginLabel;
            String formerWhileEnd = InterCodeTable.nowWhileEndLabel;
            Cond cond = (Cond) nodes.get(2);
            String whileBeginLabel = InterCodeTable.pushLabel();
            String loopBeginLabel = InterCodeTable.pushLabel();
            String loopEndLabel = InterCodeTable.pushLabel();
            LabelRP labelRP = new LabelRP(whileBeginLabel);
            InterCodeTable.addCode(labelRP);
            cond.Jump(loopBeginLabel, loopEndLabel);
            LabelRP labelRP1 = new LabelRP(loopBeginLabel);
            InterCodeTable.addCode(labelRP1);
            InterCodeTable.nowWhileBeginLabel = whileBeginLabel;
            InterCodeTable.nowWhileEndLabel = loopEndLabel;
            Stmt loopstmt = (Stmt) nodes.get(4);
            loopstmt.tointerRP();
            JumpRP jumpRP = new JumpRP(whileBeginLabel);
            InterCodeTable.addCode(jumpRP);
            LabelRP labelRP2 = new LabelRP(loopEndLabel);
            InterCodeTable.addCode(labelRP2);
            InterCodeTable.nowWhileBeginLabel = formerWhileBegin;
            InterCodeTable.nowWhileEndLabel = formerWhileEnd;
        } else if (node0.isWord(Wordtype.BREAKTK)) {
            JumpRP jumpRP = new JumpRP(InterCodeTable.nowWhileEndLabel);
            InterCodeTable.addCode(jumpRP);
        } else if (node0.isWord(Wordtype.CONTINUETK)) {
            JumpRP jumpRP = new JumpRP(InterCodeTable.nowWhileBeginLabel);
            InterCodeTable.addCode(jumpRP);
        }
        InterCodeTable.regindex = nowindex;
    }
}
